<?php
  
  /**------------------------------------------------------------------------------
   * Title:        swype decoder
   * Filename:     swypedecoder.class.php
   * Version:      0.1
   * Author:       Richard Keizer
   * Email:        ra dot keizer at gmail dot com
   *-------------------------------------------------------------------------------
   * COPYRIGHT (c) 2011 Richard Keizer
   *
   * The source code included in this package is free software; you can
   * redistribute it and/or modify it under the terms of the GNU General Public
   * License as published by the Free Software Foundation. This license can be
   * read at:
   *
   * http://www.opensource.org/licenses/gpl-license.php
   *
   * This program is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   *------------------------------------------------------------------------------
   *
   *
   */
  

  class SwypeDecoder {
    
    //
    // the constructor loads our pre-build dictionary or if it doesn't exist
    // it will create it.
    //
    
    public function __construct($lang='en') {
      if (file_exists("dictionary/{$lang}.dict")) {
        $this->words = unserialize(file_get_contents("dictionary/{$lang}.dict"));
      } else {
        $this->buildDictionary($lang);
      }
    }
    
    //
    // 'unswyping' is very easy using our pre-build dictionary
    // first we generate the key consisting of the concatenation of the first and
    // last character of the characterlist.
    // Using this key as an index in our dictionary does a very good deduction on
    // the possibilities!
    // Next we loop through the deducted list and return the first matching occurence
    // based on the regular expression. 
    
    public function unSwype($chars) {
      $suggestions = array();
      $key = $this->generateKey($chars);
      if (isset($this->words[$key])) {      
        foreach($this->words[$key] as $word => $regex) {
          if (preg_match("/{$regex}/i", $chars)) {
            $suggestions[] = $word;
          }
        }
      }
      return $suggestions;
    }
    
    protected function generateKey($word) {
      //return $word[0].$word[strlen($word)-1];
      return substr_replace($word, '', 1, -1);
    }
    
    public function buildDictionary($lang) {
      
      //
      // first we build a temp array, the words are the keys, value is length of word
      // we use this to sort the array on wordlength
      //
      $tmp = array();
      foreach (preg_split("/\R/", @file_get_contents("dictionary/{$lang}.words")) as $word) {
        if ($word) {
          $tmp[$word] = strlen($word);
        }
      }
      
      arsort($tmp);
      
      // this does the trick: for each word we generate a key. a key is the concatenation of the first and
      // last character of the word. the key is used as 1st dimension of the array.
      // 2nd dimension is the word itself.
      // the value at the [key][word] location will be a regex constructed from the word like so:
      // 'world' translates to 'w.*?o.*?r.*?l.*?d'
      // 'hello' translates to 'h.*?e.*?l.*?o'
      // notice the single 'l' in the regex for hello!
      // the reason all double chars are skipped is because of the way swype works: you can't swype double
      // characters.
      
      $this->words = array();
      foreach($tmp as $word => $dummy) {
        $regex = preg_replace('{(.)\1*}', '$1.*?', $word);    //filter out double characters etc
        $key = $this->generateKey($word);
        $this->words[$key][$word] = trim($regex, '.*?');
      }
      
      @file_put_contents("dictionary/{$lang}.dict", serialize($this->words));
    }
  }
  

  
  
